package fr.utbm.gi.vi51.slizers.framework.schedule;

import java.util.Iterator;
import java.util.logging.Logger;

import org.janusproject.kernel.agent.Agent;
import org.janusproject.kernel.agent.AgentActivator;
import org.janusproject.kernel.status.Status;
import org.janusproject.kernel.status.StatusFactory;

import fr.utbm.gi.vi51.slizers.framework.environment.Environment;

/**
 * Implementation of a scheduler for the simulation.
 *
 * @author Tarik Belabbas
 *
 */
public class SimulationScheduler extends AgentActivator
{
	/**
	 * The environment of the simulation.
	 */
	private final Environment	environment;
	
	/**
	 * The wait duration at the end of each simulation step (in milliseconds).
	 */
	private final long			waitDuration;
	
	/**
	 * The logger used to log messages of the simulation.
	 */
	private final Logger		logger	= Logger.getLogger( SimulationScheduler.class
												.getCanonicalName() );
	
	/**
	 * Boolean indicating if the simulation is in pause.
	 */
	private boolean				isPaused = false;

	/**
	 * Parameterized constructor.
	 * 
	 * @param environment the environment to schedule
	 * @param waitDuration the wait duration at the end of each simulation step
	 *            (in milliseconds).
	 */
	public SimulationScheduler( Environment _environment, long _waitDuration )
	{
		this.environment = _environment;
		this.waitDuration = _waitDuration;
	}

	/* (non-Javadoc)
	 * @see org.janusproject.kernel.agent.AgentActivator#activateBehaviour(java.util.Iterator)
	 */
	@Override
	protected Status activateBehaviour( Iterator< ? extends Agent > _agents )
	{
		Status status = StatusFactory.ok(this);
		
		if ( !this.isPaused )
		{
			this.environment.run();
			
			status = super.activateBehaviour( _agents );
		}
		
		if ( this.waitDuration > 0 )
		{
			try
			{
				Thread.sleep( this.waitDuration );
			}
			catch ( InterruptedException _exception )
			{
				this.logger.throwing( getClass().getCanonicalName(),
						"activateBehaviour", _exception ); //$NON-NLS-1$
			}
		}
		
		return status;
	}
	
	/**
	 * Pauses the simulation.
	 */
	public void pause()
	{
		this.isPaused = true;
	}
	
	/**
	 * Resumes the simulation.
	 */
	public void resume()
	{
		this.isPaused = false;
	}
}
